<template>
  <div class="image-upload">
    <Upload
      :file-list="fileList"
      name="image"
      :list-type="listType"
      class="image-upload-list"
      :custom-request="customRequest"
      :before-upload="beforeUpload"
      :multiple="multiple"
      :max-count="multiple ? maxCount : 1"
      @change="handleChange"
      @remove="handleRemove"
      @preview="handlePreview"
    >
      <div v-if="fileList.length < (multiple ? maxCount : 1)" class="upload-button">
        <PlusOutlined />
        <div style="margin-top: 8px">上传图片</div>
      </div>
    </Upload>
    
    <!-- 预览模态框 -->
    <a-modal 
      :open="previewVisible" 
      :title="previewTitle" 
      :footer="null" 
      @cancel="handleCancel"
    >
      <img alt="preview" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, watch } from 'vue';
  import { PlusOutlined } from '@ant-design/icons-vue';
  import { message, Upload } from 'ant-design-vue';
  import type { UploadFile, UploadProps } from 'ant-design-vue';
  import type { ImageUploadFile } from './types';

  defineOptions({
    name: 'ImageUpload',
    inheritAttrs: false,
  });

  interface Props {
    modelValue?: string | string[];
    multiple?: boolean;
    maxCount?: number;
    maxSize?: number; // MB
    listType?: 'text' | 'picture' | 'picture-card';
    disabled?: boolean;
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: '',
    multiple: false,
    maxCount: 9,
    maxSize: 2,
    listType: 'picture-card',
    disabled: false,
  });

  const emit = defineEmits<{
    'update:modelValue': [value: string | string[]];
    'change': [fileList: ImageUploadFile[]];
  }>();

  type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0];

  const fileList = ref<ImageUploadFile[]>([]);
  const previewVisible = ref(false);
  const previewImage = ref('');
  const previewTitle = ref('');

  // 模拟helper工具函数
  const helper = {
    toApiUrl: (path: string) => `/api/${path}`,
  };

  // 模拟API调用
  const uploadImage = async (file: FileType) => {
    return new Promise<{ md5: string }>((resolve, reject) => {
      // 模拟上传过程
      const reader = new FileReader();
      reader.onload = () => {
        // 生成简单的MD5模拟值
        const md5 = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
        setTimeout(() => {
          resolve({ md5 });
        }, 1000);
      };
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  };

  // 监听modelValue变化，初始化文件列表
  const stopWatch = watch(
    () => props.modelValue,
    (newValue) => {
      if (newValue && fileList.value.length === 0) {
        const values = props.multiple ? 
          (Array.isArray(newValue) ? newValue : [newValue]) : 
          [typeof newValue === 'string' ? newValue : ''];
        
        fileList.value = values.filter(Boolean).map((md5, index) => ({
          uid: `upload-${Date.now()}-${index}`,
          name: `image-${index + 1}`,
          status: 'done',
          url: helper.toApiUrl(`file/download2?md5=${md5}`),
          md5,
        } as ImageUploadFile));
      }
    },
    { immediate: true }
  );

  // 文件上传前的验证
  const beforeUpload = (file: FileType) => {
    const isImage = file.type.startsWith('image/');
    if (!isImage) {
      message.error('只能上传图片文件！');
      return false;
    }

    const isLtMaxSize = file.size / 1024 / 1024 < props.maxSize;
    if (!isLtMaxSize) {
      message.error(`图片大小不能超过 ${props.maxSize}MB！`);
      return false;
    }

    return true;
  };

  // 自定义上传请求
  const customRequest: UploadProps['customRequest'] = async (options) => {
    try {
      const hide = message.loading('图片上传中...', 0);
      const result = await uploadImage(options.file as FileType);
      hide();
      
      // 创建新的文件对象
      const newFile: ImageUploadFile = {
        uid: (options.file as any).uid,
        name: (options.file as any).name,
        status: 'done',
        url: helper.toApiUrl(`file/download2?md5=${result.md5}`),
        md5: result.md5,
      };

      // 更新文件列表
      if (props.multiple) {
        fileList.value = [...fileList.value, newFile];
      } else {
        fileList.value = [newFile];
      }

      updateModelValue();
      message.success('图片上传成功！');

      if (options.onSuccess) {
        options.onSuccess(result);
      }
    } catch (error) {
      message.error('图片上传失败');
      if (options.onError) {
        options.onError(error as Error);
      }
    }
  };

  // 文件状态变化
  const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
    console.log('文件列表变化:', newFileList);
    emit('change', newFileList as ImageUploadFile[]);
  };

  // 移除文件
  const handleRemove: UploadProps['onRemove'] = (file) => {
    fileList.value = fileList.value.filter(item => item.uid !== file.uid);
    updateModelValue();
  };

  // 预览图片
  const handlePreview = async (file: UploadFile) => {
    const uploadFile = file as ImageUploadFile;
    if (!file.url && !file.preview) {
      file.preview = helper.toApiUrl(`file/download2?md5=${uploadFile.md5}`);
    }
    previewImage.value = file.url || file.preview as string;
    previewVisible.value = true;
    previewTitle.value = file.name || '图片预览';
  };

  // 取消预览
  const handleCancel = () => {
    previewVisible.value = false;
    previewTitle.value = '';
  };

  // 更新modelValue
  const updateModelValue = () => {
    const md5List = fileList.value
      .filter(file => file.status === 'done' && file.md5)
      .map(file => file.md5!);

    if (props.multiple) {
      emit('update:modelValue', md5List);
    } else {
      emit('update:modelValue', md5List[0] || '');
    }
  };

  // 暴露组件方法
  defineExpose({
    fileList,
    clearFiles: () => {
      fileList.value = [];
      updateModelValue();
    },
  });
</script>

<style lang="less" scoped>
.image-upload {
  .image-upload-list {
    :deep(.ant-upload-select-picture-card) {
      width: 104px;
      height: 104px;
      margin-right: 8px;
      margin-bottom: 8px;
    }

    :deep(.ant-upload-list-picture-card-container) {
      width: 104px;
      height: 104px;
      margin-right: 8px;
      margin-bottom: 8px;
    }
  }

  .upload-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: #666;
    font-size: 14px;

    .anticon {
      font-size: 24px;
      margin-bottom: 8px;
    }
  }
}
</style> 